﻿/*
 * @author Lee 
 * Time: 20180403 
 * Abstract: SharePoint API的二次封装
 */

using System;
using System.Xml;

namespace SharePointHelper.DLL.SSOM
{
    /// <summary>
    /// 对于XML和HTML的一些操作
    /// </summary>
	public class Xml
	{
        /// <summary>
        /// 从一个XML Feed中获取一个 XML document 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="timeout">毫秒级, 默认是1 minute</param>
        /// <returns></returns>
        public static XmlDocument GetXmlDocument(string url, int? timeout)
		{
			XmlDocument xml = new XmlDocument();
			try
			{
				// 初始化
				if (!Utilities.IsValidAbsoluteUrl(url, false)) { throw new Exception("URL passed is invalid: " + url); }
				if (timeout == null) { timeout = 60000; } //6 0 seconds

				if (string.IsNullOrEmpty(url)) { throw new Exception("No URL passed to http request"); }
				System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
				request.AllowAutoRedirect = false;	// 不允许重定向,比如, 重定向登录页面
				request.Timeout = (int)timeout;
				using (System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse())
				{
					xml.Load(response.GetResponseStream());
					if (xml == null) { throw new Exception("Failed to load XML using XML url: " + url); }
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("5eiuj5eh65rtsewewrwe3", ex, "url: " + url);
				xml = null;
			}
			return xml;
		}


        /// <summary>
        /// 使用新的xml来替换 xml/html 元素 (tag)，可以替换元素内容，也可以替换整个元素。
        /// </summary>
        /// <param name="sourceXml">带有更新元素的源XML</param>
        /// <param name="newXml">要替换的新xml</param>
        /// <param name="elementName">替代的XML元素/标签。比如可以是，"div", "span", "p", or "td"</param>
        /// <param name="elementId">id="" 元素的唯一ID，这种方式不替换所有的“div”，例如。如果NULL，将替换所有带有标记名称的元素</param>
        /// <param name="isReplaceEntireElement">如果是true，将取代元素及其内容（outerxml）否则，替换该元素的内容（innerxml）</param>
        /// <returns></returns>
        public static string ReplaceElements(string sourceXml, string newXml, string elementName, string elementId, bool isReplaceEntireElement, ref int numberElementsAffected)
		{
			try
			{
				// 初始化
				if (string.IsNullOrEmpty(elementName)) { throw new Exception("No element name passed"); }
				numberElementsAffected = 0;


				if (string.IsNullOrEmpty(sourceXml)) { sourceXml = newXml; }
				else
				{
					// 将 source 传化成 XML doc
					XmlDocument doc = new XmlDocument();
					doc.LoadXml(sourceXml);

					// 获取 element(s)
					string xPath = "//" + elementName;
					if (!string.IsNullOrEmpty(elementId)) { xPath += "[@id='" + elementId + "']"; }
					XmlNodeList elements = doc.SelectNodes(xPath);
					if (elements == null || elements.Count == 0) { throw new Exception("Failed to get elements in source xml using xpath: " + xPath); }

					foreach (XmlNode n in elements)
					{
						if (!isReplaceEntireElement) { n.InnerXml = newXml; }
						else
						{
							XmlDocumentFragment fragment = doc.CreateDocumentFragment();
							fragment.InnerXml = newXml;
							n.ParentNode.ReplaceChild(fragment, n);
						}
						numberElementsAffected++;
					}
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("tduiitydhrer5", ex, "element name: " + elementName + " elementId: " + elementId +
					" source xml: " + sourceXml + " new xml: " + newXml);
			}
			return sourceXml;
		}

        /// <summary>
        /// 获取xml文本中匹配的xml节点
        /// </summary>
        /// <param name="sourceXml">xml or html source</param>
        /// <param name="elementName">xml node 名称, 比如 "div", "span", "p", etc.</param>
        /// <param name="elementId">“ID”属性的值。如果是空，则得到所有匹配其name的元素</param>
        /// <returns></returns>
        public static XmlNodeList GetElements(string sourceXml, string elementName, string elementId)
		{
			XmlNodeList elements = null;
			try
			{
				// 初始化
				if (string.IsNullOrEmpty(elementName)) { throw new Exception("No element name passed"); }


				if (!string.IsNullOrEmpty(sourceXml))
				{
                    // 将 source 传化成 XML doc
                    XmlDocument doc = new XmlDocument();
					doc.LoadXml(sourceXml);

					// 获取 element(s)
					string xPath = "//" + elementName;
					if (!string.IsNullOrEmpty(elementId)) { xPath += "[@id='" + elementId + "']"; }
					elements = doc.SelectNodes(xPath);
					if (elements == null || elements.Count == 0) { throw new Exception("Failed to get elements in source xml using xpath: " + xPath); }
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("tduiitydhrer5", ex, "element name: " + elementName + " elementId: " + elementId +
					" source html: " + sourceXml);
			}
			return elements;
		}
	}
}
